/********************************** (C) COPYRIGHT *******************************
 * File Name          : main.c
 * Author             : WCH
 * Version            : V1.0.0
 * Date               : 2021/06/06
 * Description        : Main program body.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for 
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/

/*
 *@Note
 CAN Normal mode, standard frame and expanded frame data transceiver:
 CAN_Tx(PB9),CAN_Rx(PB8)
 This routine requires an external CAN transceiver to demonstrate
 Standard_Frame and Extended_Frame.
 Standard_Frame: including 1 32bit filter mask bit pattern, 2 16bit filter
  mask bit patterns,one 32bit identifier list mode, 2 16bit identifier list modes;
 Extended_Frame: 1 32bit filter mask bit pattern.

CAN正常模式、标准帧和扩展帧数据收发器：
CAN_Tx（PB9）、CAN_Rx（PB8）
此例行程序需要一个外部CAN收发器来演示
标准帧和扩展帧。
Standard_Frame：包括1个32位滤波器掩码位模式，2个16位滤波器
掩码位模式，一个32位标识符列表模式，2个16位标识符列表方式；
Extended_Frame：1个32位滤波器掩码位模式。
*/

#include "hu.h"

//开发板用的是PB8，9，产品用的是PA11，12
#define PB89       0
#define PA1112     1
#define CANPIN PA1112

#define CmdCode_Conf 0x0607
#define CmdCode_Edition 0x0641
#define CmdCode_Recover 0x0821
#define CmdCode_Udid 0x0823


//ID设定，全0可以读所有ID ID=0x10261051  好像改了也能读？
#define IDH       0x1826//0
#define IDL       0xF456//0
#define IDMSKH    0xFFFF//0
#define IDMSKL    0xFFFF//0


//tst()里面用的，不影响其他程序
#define TX_MODE           0
#define RX_MODE           1
#define CAN_MODE          TX_MODE
//#define CAN_MODE   RX_MODE

//这个改了也能用。
#define Standard_Frame    0
#define Extended_Frame    1
//#define Frame_Format      Standard_Frame
#define Frame_Format   Extended_Frame

u32 CAN_ID_BATTER1_VOLTAGE,CAN_ID_BATTER2_VOLTAGE,CAN_ID_BATTER_STATUS,CAN_ID_CONFIG,CAN_ID_edition,CAN_ID_RECOVER,CAN_ID_UDID;


/*********************************************************************
 * @fn      CAN_Send_Msg
 *
 * @brief   CAN Transmit function.
 *
 * @param   msg - Transmit data buffer.
 *          len - Data length.
 *
 * @return  0 - Send successful.
 *          1 - Send failed.
 */
u8 CAN_T(u8 *msg, u8 len)//发送标准码id的数据
{
    u8  mbox;
    u16 i = 0;

    CanTxMsg CanTxStructure;

//    CanTxStructure.ExtId = 0x1826f456;
//    CanTxStructure.IDE = CAN_Id_Extended;



#if(Frame_Format == Standard_Frame)
    CanTxStructure.StdId = 0x357;
    CanTxStructure.IDE = CAN_Id_Standard;

#elif(Frame_Format == Extended_Frame)
    CanTxStructure.ExtId = 0x12124567;
    CanTxStructure.IDE = CAN_Id_Extended;

#endif


    CanTxStructure.RTR = CAN_RTR_Data;
    CanTxStructure.DLC = len;

    for(i = 0; i < len; i++) {
        CanTxStructure.Data[i] = msg[i];
    }

    mbox = CAN_Transmit(CAN1, &CanTxStructure);
    i = 0;

    while((CAN_TransmitStatus(CAN1, mbox) != CAN_TxStatus_Ok) && (i < 0xFFF))
    {
        i++;
    }

    if(i == 0xFFF)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}



u8 CAN_T1(u32 Extid,u8 *msg, u8 len)//发送扩展码id的数据
{
    u8  mbox;
    u16 i = 0;

    CanTxMsg CanTxStructure;

    CanTxStructure.ExtId =  Extid;
    CanTxStructure.IDE = CAN_Id_Extended;

    CanTxStructure.RTR = CAN_RTR_Data;
    CanTxStructure.DLC = len;

    for(i = 0; i < len; i++) {
        CanTxStructure.Data[i] = msg[i];
    }

    mbox = CAN_Transmit(CAN1, &CanTxStructure);
    i = 0;

    while((CAN_TransmitStatus(CAN1, mbox) != CAN_TxStatus_Ok) && (i < 0xFFF))
    {
        i++;
    }

    if(i == 0xFFF)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
/*********************************************************************
 * @fn      CAN_Receive_Msg
 *
 * @brief   CAN Receive function.
 *
 * @param   buf - Receive data buffer.
 *          len - Data length.
 *
 * @return  CanRxStructure.DLC - Receive data length.
 */

u8 MyCan_ReceiveFlag(void)
{
	if(CAN_MessagePending(CAN1,CAN_FIFO0) > 0)
	{
		return 1;
	}
	return 0;
}

typedef struct CAN_STRUCT
{
    u16 addr;
    u16 cmd;
}CAN_EXTIDDATA;



CAN_EXTIDDATA decodeExtID(uint32_t extid)
{
    CAN_EXTIDDATA canbuf;
    uint8_t pbuf = (uint8_t)(extid>>26);
    uint8_t pfbuf = (uint8_t)(extid>>16);
    canbuf.addr = (uint16_t)(extid>>8);
    canbuf.cmd = ((u16)pbuf<<8)|(u16)(pfbuf);
    return canbuf;
}

u8 CAN_R(u8 *buf)
{
    u8 i;
    CanRxMsg CanRxStructure;

    CAN_Receive(CAN1, CAN_FIFO0, &CanRxStructure);
    CAN_EXTIDDATA MY_EXTIDATA;
    MY_EXTIDATA = decodeExtID(CanRxStructure.ExtId);


    if (CanRxStructure.RTR == CAN_RTR_Remote)
    {   
        Delay_Ms(100);
        if(MY_EXTIDATA.cmd == CmdCode_Conf)
        {
           u8 Temp_Data[2] = {0x06,0x06};            
           CAN_T1(CAN_ID_CONFIG,Temp_Data,2);            
        }
        else if(MY_EXTIDATA.cmd == CmdCode_Edition)
        {
           u8 Temp_Data[2] = {0x06,0x40};            
           CAN_T1(CAN_ID_edition,Temp_Data,2);              
        }
        else if(MY_EXTIDATA.cmd == CmdCode_Recover)
        {
           u8 Temp_Data[2] = {0x02,0x20};            
           CAN_T1(CAN_ID_RECOVER,Temp_Data,2);              
        }
        else if(MY_EXTIDATA.cmd == CmdCode_Udid)
        {
           u8 Temp_Data[2] = {0x02,0x22};            
           CAN_T1(CAN_ID_UDID,Temp_Data,2);              
        }

    }
    else if(CanRxStructure.RTR == CAN_RTR_Data)
    {

    }

    printf("CAN_RxData is :");

    for(i = 0; i < 8; i++) {
        buf[i] = CanRxStructure.Data[i];

        printf("%x ", buf[i]);
    }

     printf("\r\n");

    return CanRxStructure.DLC;
}



/*********************************************************************
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int tst(void)
{
    u8 i = 0;
    u8 cnt = 1;
    u8 px;
    u8 pxbuf[8];

    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n", SystemCoreClock);

    /* Bps = 333Kbps */
    CAN_INI(CAN_SJW_1tq, CAN_BS2_5tq, CAN_BS1_6tq, 12, CAN_Mode_Normal);

    while(1)
    {
#if(CAN_MODE == TX_MODE)
        for(i = 0; i < 8; i++)        
            pxbuf[i] = cnt + i;
        
        px = CAN_T(pxbuf, 8);

        if(px)        
            printf("Send Failed\r\n");        
        else
        {
            printf("Send Success\r\n");
            printf("Send Data:\r\n");

            for(i = 0; i < 8; i++) 
                printf("%02x\r\n", pxbuf[i]);
            
        }

#elif(CAN_MODE == RX_MODE)
        px = CAN_R(pxbuf);

        if(px)
        {
            printf("Receive Data:\r\n");

            for(i = 0; i < 8; i++) {
                printf("%02x\r\n", pxbuf[i]);
            }
        }

#endif

        Delay_Ms(1000);
        cnt++;

        if(cnt == 0xFF)        
            cnt = 0;
        
    }
}

/*********************************************************************
 * @fn      CAN_Mode_Init
 *
 * @brief   Initializes CAN communication test mode.
 *          Bps =Fpclk1/((tpb1+1+tbs2+1+1)*brp)
 *
 * @param   tsjw - CAN synchronisation jump width.
 *          tbs2 - CAN time quantum in bit segment 1.
 *          tbs1 - CAN time quantum in bit segment 2.
 *          brp - Specifies the length of a time quantum.
 *          mode - Test mode.
 *            CAN_Mode_Normal.
 *            CAN_Mode_LoopBack.
 *            CAN_Mode_Silent.
 *            CAN_Mode_Silent_LoopBack.
 *
 * @return  none
 */
void CAN_INI(u8 tsjw, u8 tbs2, u8 tbs1, u16 brp, u8 mode)
{
    GPIO_InitTypeDef      GPIO_InitSturcture = {0};
    CAN_InitTypeDef       CAN_InitSturcture = {0};
    CAN_FilterInitTypeDef CAN_FilterInitSturcture = {0};

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
#if(CANPIN == PB89)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);

    GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);//重映射

    GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitSturcture);

    GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOB, &GPIO_InitSturcture);
#elif(CANPIN == PA1112)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitSturcture);

    GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitSturcture);
#endif
    CAN_InitSturcture.CAN_TTCM = DISABLE;
    CAN_InitSturcture.CAN_ABOM = DISABLE;
    CAN_InitSturcture.CAN_AWUM = ENABLE;
    CAN_InitSturcture.CAN_NART = ENABLE;
    CAN_InitSturcture.CAN_RFLM = DISABLE;
    CAN_InitSturcture.CAN_TXFP = DISABLE;
    CAN_InitSturcture.CAN_Mode = mode;////模式设置：0,普通模式;1,回环模式;
    CAN_InitSturcture.CAN_SJW = tsjw;
    CAN_InitSturcture.CAN_BS1 = tbs1;
    CAN_InitSturcture.CAN_BS2 = tbs2;
    CAN_InitSturcture.CAN_Prescaler = brp;
    CAN_Init(CAN1, &CAN_InitSturcture);

    CAN_FilterInitSturcture.CAN_FilterNumber = 0;

#if(Frame_Format == Standard_Frame)//ID=0x10261051
    /* identifier/mask mode, One 32-bit filter, StdId: 0x317 */

    CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdMask;//CAN_FilterMode_IdList;//;
    CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit;//CAN_FilterScale_16bit;
    CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x0000;//IDH;//0x62E0;
    CAN_FilterInitSturcture.CAN_FilterIdLow = 0x0000;//0x246<<5;246H*20H=48c0//IDL;
    CAN_FilterInitSturcture.CAN_FilterMaskIdHigh =0x0000;
    CAN_FilterInitSturcture.CAN_FilterMaskIdLow =0x0000;//IDMSKL;// 0x0006;


//    CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdList;
//    CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_16bit;
//    CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x246<<5;
//    CAN_FilterInitSturcture.CAN_FilterIdLow = 0x246<<5;
//    CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0x246<<5;
//    CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0x246<<5;

//    CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdMask;
//    CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit;
//    CAN_FilterInitSturcture.CAN_FilterIdHigh = 0;//0x62E0;
//    CAN_FilterInitSturcture.CAN_FilterIdLow = 0;
//    CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0;//0xFFE0;
//    CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0;//0x0006;

    /* identifier/mask mode, Two 16-bit filters, StdId: 0x317��0x316 */
//    	CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdMask;
//    	CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_16bit;
//    	CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x48c0;
//    	CAN_FilterInitSturcture.CAN_FilterIdLow = 0xFFFF;
//    	CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0x48c0;
//    	CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0xFFFF;

    /* identifier list mode, One 32-bit filter, StdId: 0x317��0x316 */
//    	CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdList;
//    	CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit;
//    	CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x62E0;
//    	CAN_FilterInitSturcture.CAN_FilterIdLow = 0;
//    	CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0x62C0;
//    	CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0;

    /* identifier list mode, Two 16-bit filters, StdId: 0x317,0x316,0x315,0x314 */
    //	CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdList;
    //	CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_16bit;
    //	CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x62E0;
    //	CAN_FilterInitSturcture.CAN_FilterIdLow = 0x62C0;
    //	CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0x62A0;
    //	CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0x6280;


#elif(Frame_Format == Extended_Frame)
    /* identifier/mask mode, One 32-bit filter, ExtId: 0x12124567 */
    CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdMask;
    CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit;

	uint32_t ID = (0x0000f600 << 3) | 0x2;
	CAN_FilterInitSturcture.CAN_FilterIdHigh = ID >> 16;
	CAN_FilterInitSturcture.CAN_FilterIdLow = ID;
	
	uint32_t Mask = (0x1000ff00 << 3)  | 0x2;
	CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = Mask >> 16;
	CAN_FilterInitSturcture.CAN_FilterMaskIdLow = Mask;

#endif

    CAN_FilterInitSturcture.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
    CAN_FilterInitSturcture.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitSturcture);




}

